home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 20 code / Pict Tricks / Batch CLUTLess / Lib Files / SelectFolder.c < prev   
Encoding:
C/C++ Source or Header  |  1994-08-31  |  7.4 KB  |  320 lines  |  [TEXT/MMCC]

  1. /*    StandardGetFolder example
  2.  
  3.     Steve Falkenburg -- MacDTS
  4.     
  5.     This sample uses the new System 7 CustomGetFile routine
  6.     to provide a StandardGetFolder call to be used by applications
  7.     when the user needs to select a folder instead of a file.
  8.     
  9.     It's written in Think C, but should work in MPW if a few #include
  10.     files are added.
  11.     
  12.     The style of the dialog box is taken from the Human Interface note
  13.     on folder selection.
  14.     
  15.     SJF        5/2/92        added check for empty filename and call to MakeFSSpec
  16.     SJF        5/2/92        added check for refcon in filter and hook routines
  17.     SJF        10/30/91    original coding
  18.     
  19. */
  20.  
  21. #include <Aliases.h>
  22. #include <string.h>
  23. #include <Folders.h>
  24.  
  25. /* prototypes */
  26.  
  27. void InitSelectFolder(void);
  28. Boolean CustomGet(FSSpec *fSpec);
  29. pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData);
  30. pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData);
  31. void HitButton(DialogPtr theDlg,short item);
  32. pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
  33. void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg);
  34. Boolean SameFile(FSSpec *file1,FSSpec *file2);
  35. Boolean GetFSSpecPartialName(FSSpec *file,StringPtr fName);
  36. OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum);
  37. OSErr MakeCanonFSSpec(FSSpec *fSpec);
  38. Boolean ShouldHiliteSelect(FSSpec *fSpec);
  39.  
  40. /* typedefs */
  41.  
  42. typedef struct {
  43.     StandardFileReply *replyPtr;
  44.     FSSpec oldSelection;
  45. } SFData, *SFDataPtr;
  46.  
  47. /* constants */
  48.  
  49. #define    kSelectItem            10
  50. #define    kSFDlg                129
  51. #define    kCanSelectDesktop    true
  52. #define    kSelectStrRsrc        128
  53. #define kDefaultSelectString "\pSelect"
  54. #define    kDeskStrRsrc        129
  55. #define    kDefaultDeskString    "\pDesktop"
  56. #define    kSelectKey            's'
  57.  
  58. /* globals */
  59.  
  60. FSSpec gDeskFolderSpec;
  61. Str255 gSelectString;
  62. Str255 gDesktopFName;
  63.  
  64.  
  65. /* initialize managers */
  66.  
  67. void InitSelectFolder(void)
  68. {
  69.     Handle strHndl;
  70.     
  71.     strHndl = Get1Resource('STR ',kSelectStrRsrc);
  72.     if (ResError()!=noErr || !strHndl || !*strHndl)
  73.         BlockMove(kDefaultSelectString,gSelectString,kDefaultSelectString[0]+1);
  74.     else {
  75.         BlockMove(*strHndl,&gSelectString,(long)((unsigned char *)(*strHndl)[0]+1));
  76.         ReleaseResource(strHndl);
  77.     }
  78.  
  79.     strHndl = Get1Resource('STR ',kDeskStrRsrc);
  80.     if (ResError()!=noErr || !strHndl || !*strHndl)
  81.         BlockMove(kDefaultDeskString,gDesktopFName,kDefaultSelectString[0]+1);
  82.     else {
  83.         BlockMove(*strHndl,&gDesktopFName,(long)((unsigned char *)(*strHndl)[0]+1));
  84.         ReleaseResource(strHndl);
  85.     }
  86. }
  87.  
  88.  
  89. /* do getfile */
  90.  
  91. Boolean CustomGet(FSSpec *fSpec)
  92. {
  93.     Point where = {-1,-1};
  94.     StandardFileReply sfReply;
  95.     SFData sfUserData;
  96.     OSErr err;
  97.     Boolean targetIsFolder,wasAliased;
  98.     
  99.     /* initialize user data area */
  100.     
  101.     sfUserData.replyPtr = &sfReply;
  102.     sfUserData.oldSelection.vRefNum = -9999;    /* init to ridiculous value */
  103.     
  104.     CustomGetFile((FileFilterYDProcPtr)FilterAllFiles,-1,nil,&sfReply,kSFDlg,where,MyDlgHook,
  105.                     MyModalFilter,nil,nil,&sfUserData);
  106.     
  107.     if (sfReply.sfGood) {
  108.         err = ResolveAliasFile(&sfReply.sfFile,true,&targetIsFolder,&wasAliased);
  109.         if (err!=noErr)
  110.             return false;
  111.     }
  112.     
  113.     err = FSMakeFSSpec(sfReply.sfFile.vRefNum,sfReply.sfFile.parID,sfReply.sfFile.name,fSpec);
  114.     if (err!=noErr)
  115.         return false;
  116.     
  117.     return sfReply.sfGood;
  118. }
  119.  
  120.  
  121. /*    this dialog hook checks the contents of the additional edit fields
  122.     when the user selects a file.  The focus of the dialog is changed if one
  123.     of the fields is out of range.
  124. */
  125.  
  126. pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData)
  127. {
  128.     SFDataPtr sfUserData;
  129.     FSSpec curSpec;
  130.     OSType refCon;
  131.     
  132.     refCon = GetWRefCon(theDlg);
  133.     if (refCon!=sfMainDialogRefCon)
  134.         return item;
  135.         
  136.     sfUserData = (SFDataPtr) userData;
  137.     
  138.     if (item==sfHookFirstCall || item==sfHookLastCall)
  139.         return item;
  140.     
  141.     if (item==sfItemVolumeUser) {
  142.         sfUserData->replyPtr->sfFile.name[0] = '\0';
  143.         sfUserData->replyPtr->sfFile.parID = 2;
  144.         sfUserData->replyPtr->sfIsFolder = false;
  145.         sfUserData->replyPtr->sfIsVolume = false;
  146.         sfUserData->replyPtr->sfFlags = 0;
  147.         item = sfHookChangeSelection;
  148.     }
  149.         
  150.     if (!SameFile(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection)) {
  151.         BlockMove(&sfUserData->replyPtr->sfFile,&curSpec,sizeof(FSSpec));
  152.         MakeCanonFSSpec(&curSpec);
  153.         
  154.         if (curSpec.vRefNum!=sfUserData->oldSelection.vRefNum)
  155.             GetDeskFolderSpec(&gDeskFolderSpec,curSpec.vRefNum);    
  156.         SetSelectButtonName(curSpec.name,ShouldHiliteSelect(&curSpec),theDlg);
  157.         
  158.         BlockMove(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection,sizeof(FSSpec));
  159.     }
  160.     
  161.     if (item==kSelectItem)
  162.         item = sfItemOpenButton;
  163.         
  164.     return item;
  165. }
  166.  
  167.  
  168. pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData)
  169. {
  170.     Boolean evHandled;
  171.     char keyPressed;
  172.     OSType refCon;
  173.     
  174.     refCon = GetWRefCon(theDlg);
  175.     if (refCon!=sfMainDialogRefCon)
  176.         return false;
  177.         
  178.     evHandled = false;
  179.     
  180.     switch (ev->what) {
  181.         case keyDown:
  182.         case autoKey:
  183.             keyPressed = ev->message & charCodeMask;
  184.             if ((ev->modifiers & cmdKey) != 0) {
  185.                 switch (keyPressed) {
  186.                     case kSelectKey:
  187.                         HitButton(theDlg,kSelectItem);
  188.                         *itemHit = kSelectItem;
  189.                         evHandled = true;
  190.                         break;
  191.                 }
  192.             }
  193.             break;
  194.     }
  195.     
  196.     return evHandled;
  197. }
  198.  
  199.  
  200. void HitButton(DialogPtr theDlg,short item)
  201. {
  202.     short iType;
  203.     ControlHandle iHndl;
  204.     Rect iRect;
  205.     long fTicks;
  206.     
  207.     GetDItem(theDlg,item,&iType,(Handle *)&iHndl,&iRect);
  208.     HiliteControl(iHndl,inButton);
  209.     Delay(5,&fTicks);
  210.     HiliteControl(iHndl,0);
  211. }
  212.  
  213.  
  214. pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
  215. {
  216.     if (pb->hFileInfo.ioFlAttrib & (1<<4))    /* file is a directory */
  217.         return false;
  218.  
  219.     return true;
  220. }
  221.  
  222.  
  223. void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg)
  224. {
  225.     short iType;
  226.     Handle iHndl;
  227.     Rect iRect;
  228.     Str255 storeName,tempLenStr,tempSelName;
  229.     short btnWidth;
  230.     
  231.     BlockMove(selName,tempSelName,selName[0]+1);
  232.     GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
  233.     
  234.     /* truncate select name to fit in button */
  235.     
  236.     btnWidth = iRect.right - iRect.left;
  237.     BlockMove(gSelectString,tempLenStr,gSelectString[0]+1);
  238.     p2cstr(tempLenStr);
  239.     strcat((char *)tempLenStr," “”  ");
  240.     c2pstr((char *)tempLenStr);
  241.     btnWidth -= StringWidth(tempLenStr);
  242.     TruncString(btnWidth,tempSelName,smTruncMiddle);
  243.     
  244.     BlockMove(gSelectString,storeName,gSelectString[0]+1);
  245.     p2cstr(storeName);
  246.     p2cstr(tempSelName);
  247.     strcat((char *)storeName," “");
  248.     strcat((char *)storeName,(char *)tempSelName);
  249.     strcat((char *)storeName,"”");
  250.     
  251.     c2pstr((char *)storeName);
  252.     c2pstr((char *)tempSelName);
  253.     SetCTitle((ControlHandle)iHndl,storeName);
  254.     
  255.     SetDItem(theDlg,kSelectItem,iType,iHndl,&iRect);
  256.  
  257.     if (hilited)
  258.         HiliteControl((ControlHandle)iHndl,0);
  259.     else
  260.         HiliteControl((ControlHandle)iHndl,255);        
  261. }
  262.  
  263.  
  264. Boolean SameFile(FSSpec *file1,FSSpec *file2)
  265. {
  266.     if (file1->vRefNum != file2->vRefNum)
  267.         return false;
  268.     if (file1->parID != file2->parID)
  269.         return false;
  270.     if (!EqualString(file1->name,file2->name,false,true))
  271.         return false;
  272.     
  273.     return true;
  274. }
  275.  
  276.  
  277. OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum)
  278. {
  279.     OSErr err;
  280.     
  281.     fSpec->name[0] = '\0';
  282.     err = FindFolder(vRefNum,kDesktopFolderType,kDontCreateFolder,
  283.                         &fSpec->vRefNum,&fSpec->parID);
  284.     if (err!=noErr)
  285.         return err;
  286.     
  287.     return MakeCanonFSSpec(fSpec);
  288. }
  289.  
  290.  
  291. Boolean ShouldHiliteSelect(FSSpec *fSpec)
  292. {
  293.     if (SameFile(fSpec,&gDeskFolderSpec)) {
  294.         BlockMove(gDesktopFName,fSpec->name,gDesktopFName[0]+1);
  295.         return kCanSelectDesktop;
  296.     }
  297.     else
  298.         return true;
  299. }
  300.  
  301.  
  302. OSErr MakeCanonFSSpec(FSSpec *fSpec)
  303. {
  304.     DirInfo infoPB;
  305.     OSErr err;
  306.  
  307.     if (fSpec->name[0] != '\0')
  308.         return -1;
  309.         
  310.     infoPB.ioNamePtr = fSpec->name;
  311.     infoPB.ioVRefNum = fSpec->vRefNum;
  312.     infoPB.ioDrDirID = fSpec->parID;
  313.     infoPB.ioFDirIndex = -1;
  314.     err = PBGetCatInfo((CInfoPBPtr)&infoPB,false);
  315.     fSpec->parID = infoPB.ioDrParID;
  316.     
  317.     return err;
  318. }
  319.  
  320.